#include "io_base.h"
#include "def.h"

typedef struct log_conf {
	io_base_conf_t base_conf;
	char name[256];
	uint32_t max_size;
}log_conf_t;

typedef struct log_serv {
	io_base_t *priv;
	log_conf_t conf;
	int fd;
	uint32_t size;
}log_serv_t;

static log_serv_t g_log_server = {
	.priv = NULL,
	.conf = {
		.name = "/tmp/log/log.txt",
		.base_conf = {
			.name = "log-serv",
			.ip = "127.0.0.1",
			.port = 8001,
			.mask = NULL,
		},
	},
	.fd = -1,
};

static int do_accept_event(log_serv_t *self, io_event_t *ev)
{
	sock_t s;
	io_client_t *cli = (io_client_t *)MALLOC(sizeof(io_client_t));
	if (!cli) {
		ERR("malloc fail");
		return -1;
	}

	if (io_base_accept(self->priv, &s) < 0) {
		ERR("accept fail");
		goto _fail;
	}

	if (io_client_init(cli, &s, self->priv) < 0) {
		DBG("io_client_init fai");
		goto _fail;
	}
	return 0;

_fail:
	safe_free(cli);
	return -1;
}

static int do_signal_event(log_serv_t *self, io_event_t *ev)
{
	int signo = io_base_signo(self->priv);
	DBG("SIGNAL NO: %u", signo);
	return 0;
}

static int do_error_event(log_serv_t *self, io_event_t *ev)
{
	io_client_t *cli = ev->ctx;
	return io_client_put(cli);
}

static int do_close_event(log_serv_t *self, io_event_t *ev)
{
	io_client_t *cli = ev->ctx;
	return io_client_put(cli);
}

static int do_read_event(log_serv_t *self, io_event_t *ev)
{
	// to be continue;
	io_client_t *cli = ev->ctx;
	printf("len: %u, in_buf: %s", cli->in_len, cli->in_buf);
	fd_write(self->fd, cli->in_buf, cli->in_len);
	return 0;
}

static int do_write_event(log_serv_t *self, io_event_t *ev)
{
	assert(0);
	return 0;
}

static int do_ctrl_event(log_serv_t *self, io_event_t *ev)
{
	assert(0);
	return 0;
}

int main(int argc, char **argv)
{
	g_log_server.priv = io_base_new(&g_log_server.conf.base_conf);
	if (g_log_server.priv == NULL) {
		ERR("io_base_new fail");
		return -1;
	}

	g_log_server.fd = open(g_log_server.conf.name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
	if (g_log_server.fd < 0) {
		ERR("open fail");
		io_base_destroy(&g_log_server.priv);
		return -1;
	}

	int timeout = -1;
	io_event_t *io_ev = NULL;
	io_event_iterator_t it;
	while (1) {
		int num = io_base_loop(g_log_server.priv, timeout);
		if (num <= 0) {
			ERR("io_base_loop fail");
			break;
		}

		io_event_iterator_init(g_log_server.priv, &it);
		while ((io_ev = io_events_next(&it))) {
			switch(io_ev->event) {
			case IO_EVENT_ACCEPT:
				DBG("accept event:");
				do_accept_event(&g_log_server, io_ev);
				break;
			case IO_EVENT_SIGNAL:
				DBG("signal event:");
				do_signal_event(&g_log_server, io_ev);
				break;
			case IO_EVENT_ERROR:
				DBG("error event:");
				do_error_event(&g_log_server, io_ev);
				break;
			case IO_EVENT_CLOSE:
				DBG("close event:");
				do_close_event(&g_log_server, io_ev);
				break;
			case IO_EVENT_READ:
				DBG("read event:");
				do_read_event(&g_log_server, io_ev);
				break;
			case IO_EVENT_WRITE:
				DBG("write event:");
				do_write_event(&g_log_server, io_ev);
				break;
			case IO_EVENT_CTRL:
				DBG("ctrl event:");
				do_ctrl_event(&g_log_server, io_ev);
				break;
			case IO_EVENT_UNKNOW:
				DBG("unknow event:");
				break;
			default:
				break;
			}	
		}
		io_event_iterator_term(&it);
	}

	DBG("exiting ...");
	io_base_destroy(&g_log_server.priv);
	safe_close(g_log_server.fd);
	return 0;
}

int log_serv_stop(void)
{
	return io_base_stop(g_log_server.priv);
}
